use std::{
    sync::{
        mpsc::{self, TryRecvError},
        Arc,
    },
    thread,
    time::Duration,
};
use log::*;
pub struct Remover {
    vec1: Vec<u64>,
    vec2: Vec<u64>,
    sender: mpsc::Sender<Vec<u64>>,
    receiver: mpsc::Receiver<Vec<u64>>,
    max_thread: u64,
}
impl Clone for Remover{
    fn clone(&self) -> Self {
        Self::new(self.vec1.clone(), self.vec2.clone())
    }
}
const MAX_THREAD: u64 = 20;
impl Remover {
    pub fn new(vec1: Vec<u64>, vec2: Vec<u64>) -> Self {
        info!("a new Remover inited");
        let channel = mpsc::channel();
        Remover {
            vec1,
            vec2,
            sender: channel.0,
            receiver: channel.1,
            max_thread: MAX_THREAD,
        }
    }
}
impl Remover {
    fn in_thread(sender: mpsc::Sender<Vec<u64>>, search_vec: Arc<Vec<u64>>, vec: Vec<u64>) {
        trace!("search: {:?}, alloced: {:?}", search_vec, vec);
        let mut result = Vec::new();
        for i in vec.into_iter() {
            if !search_vec.contains(&i) {
                result.push(i);
            }
        }
        trace!("NEED RETURN: {:?}", &result);
        sender.send(result).unwrap();
    }
    fn start_new_thread(sender: mpsc::Sender<Vec<u64>>, search: Arc<Vec<u64>>, vec1: Vec<u64>) {
        thread::spawn(move || {
            info!("spawn a new thread");
            Self::in_thread(sender, search, vec1);
        });
    }
    pub fn start_not_none(self) -> Vec<u64> {
        let source = Arc::new(self.vec1);
        let sender = self.sender;
        let receiver = self.receiver;
        let chunk_size = self.vec2.len() as u64/ self.max_thread;
        let chunk_size = if let 0 = chunk_size{
            1
        }else{
            chunk_size
        };
        for i in self.vec2.chunks(chunk_size as usize) {
            Self::start_new_thread(sender.clone(), source.clone(), i.to_vec());
        }
        let mut result = Vec::new();
        let mut had_recved: u64 = 0;
        while self.max_thread != had_recved {
            match receiver.try_recv() {
                Ok(mut a) => {
                    result.append(&mut a);
                    had_recved += 1;
                }
                Err(err) => match err {
                    TryRecvError::Empty => (),
                    TryRecvError::Disconnected => panic!("It shouldn't append!Channel dead!"),
                },
            };
            thread::sleep(Duration::from_millis(50));
        }
        info!("Remove repetition done");
        result
    }
    pub fn start(mut self) -> Vec<u64>{
        if self.vec1.is_empty()||self.vec2.is_empty(){
            //empty
            let mut tmp = Vec::new();
            tmp.append(&mut self.vec1);
            tmp.append(&mut self.vec2);
            tmp
        }else{
            //not empty
            let mut tmp_self = self.clone();
            let tmp1 = tmp_self.vec1;
            tmp_self.vec1 = tmp_self.vec2;
            tmp_self.vec2 = tmp1;
            let mut result = Vec::new();
            result.append(&mut tmp_self.start_not_none());
            result.append(&mut self.start_not_none());
            result

        }
    }
}
